package trace

import (
	"encoding/base64"

	"xp/lib/jsonx"
)

func (v *Span) Len() int {
	var l int

	l += len(v.Name)
	l += v.Start.Len()
	l += v.End.Len()
	for _, val := range v.Labels {
		l += len(val) + 3
	}
	// jsonx:unsafe: 最坏的情况是每个字符都需要转义
	l += len(v.Labels)
	for _, val := range v.Labels {
		l += len(val) + 3
	}
	l += base64.StdEncoding.EncodedLen(len(v.Error))
	return l + 115
}

func (v *Span) MarshalJsonx(buf []byte) (int, error) {
	var err error
	var i, n int
	var tb [30]byte

	_ = n
	_ = err
	_ = tb

	i += copy(buf[i:], `{"id":"`)
	i += jsonx.FormatBits(buf[i:], uint64(v.ID), v.ID < 0)
	i += copy(buf[i:], `","name":"`)
	i += copy(buf[i:], v.Name)
	i += copy(buf[i:], `","start":`)
	n, err = v.Start.MarshalJsonx(buf[i:])
	if err != nil {
		return 0, err
	}
	i += n
	i += copy(buf[i:], `,"end":`)
	n, err = v.End.MarshalJsonx(buf[i:])
	if err != nil {
		return 0, err
	}
	i += n
	i += copy(buf[i:], `,"labels":[`)
	if len(v.Labels) > 0 {
		for j := 0; j < len(v.Labels)-1; j++ {
			i += copy(buf[i:], `"`)
			i += jsonx.AppendString(buf[i:], v.Labels[j])
			i += copy(buf[i:], `"`)
			i += copy(buf[i:], `,`)
		}
		i += copy(buf[i:], `"`)
		i += jsonx.AppendString(buf[i:], v.Labels[len(v.Labels)-1])
		i += copy(buf[i:], `"`)
	}
	i += copy(buf[i:], `],"parent_id":"`)
	i += jsonx.FormatBits(buf[i:], uint64(v.ParentID), v.ParentID < 0)
	i += copy(buf[i:], `","error":"`)
	base64.StdEncoding.Encode(buf[i:], v.Error)
	i += base64.StdEncoding.EncodedLen(len(v.Error))
	i += copy(buf[i:], `"}`)
	return i, nil
}

func (v *Trace) Len() int {
	var l int

	l += len(v.ID)
	l += len(v.Host)
	l += len(v.Service)
	l += len(v.Revision)
	for _, val := range v.Spans {
		l += val.Len() + 1
	}
	return l + 88
}

func (v *Trace) MarshalJsonx(buf []byte) (int, error) {
	var err error
	var i, n int
	var tb [30]byte

	_ = n
	_ = err
	_ = tb

	i += copy(buf[i:], `{"id":"`)
	i += copy(buf[i:], v.ID)
	i += copy(buf[i:], `","host":"`)
	i += copy(buf[i:], v.Host)
	i += copy(buf[i:], `","port":"`)
	i += jsonx.FormatBits(buf[i:], uint64(v.Port), v.Port < 0)
	i += copy(buf[i:], `","service":"`)
	i += copy(buf[i:], v.Service)
	i += copy(buf[i:], `","revision":"`)
	i += copy(buf[i:], v.Revision)
	i += copy(buf[i:], `","spans":[`)
	if len(v.Spans) > 0 {
		for j := 0; j < len(v.Spans)-1; j++ {
			n, err = v.Spans[j].MarshalJsonx(buf[i:])
			if err != nil {
				return 0, err
			}
			i += n
			i += copy(buf[i:], `,`)
		}
		n, err = v.Spans[len(v.Spans)-1].MarshalJsonx(buf[i:])
		if err != nil {
			return 0, err
		}
		i += n
	}
	i += copy(buf[i:], `]}`)
	return i, nil
}
